#ifndef __FATBINARYCTL_H__
#define __FATBINARYCTL_H__

#include <fatbinary.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct fatBinaryCtlHandle *fatBinaryCtl_t;
typedef const struct fatBinaryCtlHandle *fatBinaryCtl_ct;

/* TODO: maca_v2_skipped - not support now (qli2) */

typedef enum {
    FBCTL_ERROR_NONE = 0,
    FBCTL_ERROR_NULL,                    /* null pointer */
    FBCTL_ERROR_UNRECOGNIZED,            /* unrecognized kind */
    FBCTL_ERROR_NO_CANDIDATE,            /* no candidate found */
    FBCTL_ERROR_COMPILE_FAILED,          /* no candidate found */
    FBCTL_ERROR_INTERNAL,                /* unexpected internal error */
    FBCTL_ERROR_COMPILER_LOAD_FAILED,    /* loading compiler library failed */
    FBCTL_ERROR_UNSUPPORTED_PTX_VERSION, /* ptx version not supported by the compiler */
} fatBinaryCtlError_t;
const char *fatBinaryCtl_Errmsg(fatBinaryCtlError_t e) { return nullptr; }

/* Cannot change directly to opaque handle without causing warnings,
 * so add new CreateHandle routine and eventually switch everyone to it. */
fatBinaryCtlError_t fatBinaryCtl_Create(fatBinaryCtl_t *handle) { return FBCTL_ERROR_NONE; }
fatBinaryCtlError_t fatBinaryCtl_CreateHandle(fatBinaryCtl_t *handle);

void fatBinaryCtl_Delete(fatBinaryCtl_t handle) {}

/* Set (fatbin or elf) binary that we will search */
fatBinaryCtlError_t fatBinaryCtl_SetBinary(fatBinaryCtl_t handle, const void *binary)
{
    return FBCTL_ERROR_NONE;
}

/* Set target SM that we are looking for */
fatBinaryCtlError_t fatBinaryCtl_SetTargetSM(fatBinaryCtl_t handle, unsigned int arch)
{
    return FBCTL_ERROR_NONE;
}

typedef enum {
    fatBinary_PreferBestCode, /* default */
    fatBinary_AvoidPTX,       /* use sass if possible for compile-time savings */
    fatBinary_ForcePTX,       /* use ptx (mainly for testing) */
    fatBinary_JITIfNotMatch,  /* use ptx if arch doesn't match */
    fatBinary_PreferNvvm,     /* choose NVVM IR when available */
    fatBinary_LinkCompatible, /* use sass if link-compatible */
    fatBinary_PreferMercury,  /* choose mercury over sass */
} fatBinary_CompilationPolicy;
/* Set policy for how we handle JIT compiles */
fatBinaryCtlError_t fatBinaryCtl_SetPolicy(fatBinaryCtl_t handle,
                                           fatBinary_CompilationPolicy policy)
{
    return FBCTL_ERROR_NONE;
}

/* Set ptxas options for JIT compiles */
fatBinaryCtlError_t fatBinaryCtl_SetPtxasOptions(fatBinaryCtl_t handle, const char *options)
{
    return FBCTL_ERROR_NONE;
}

/* Set flags for fatbinary */
fatBinaryCtlError_t fatBinaryCtl_SetFlags(fatBinaryCtl_t handle, long long flags)
{
    return FBCTL_ERROR_NONE;
}

/* Return identifier string for fatbinary */
fatBinaryCtlError_t fatBinaryCtl_GetIdentifier(fatBinaryCtl_ct handle, const char **id)
{
    return FBCTL_ERROR_NONE;
}
/* Return ptxas options for fatbinary */
fatBinaryCtlError_t fatBinaryCtl_GetPtxasOptions(fatBinaryCtl_ct handle, const char **options)
{
    return FBCTL_ERROR_NONE;
}

/* Return cicc options for fatbinary */
fatBinaryCtlError_t fatBinaryCtl_GetCiccOptions(fatBinaryCtl_ct handle, const char **options)
{
    return FBCTL_ERROR_NONE;
}

/* Return whether fatbin has debug code (1 == true, 0 == false) */
fatBinaryCtlError_t fatBinaryCtl_HasDebug(fatBinaryCtl_ct handle, int *debug)
{
    return FBCTL_ERROR_NONE;
}

/* Using the input values, pick the best candidate */
fatBinaryCtlError_t fatBinaryCtl_PickCandidate(fatBinaryCtl_t handle) { return FBCTL_ERROR_NONE; }

/*
 * Using the previously chosen candidate, compile the code to elf,
 * returning elf image and size.
 * Note that because elf is allocated inside fatBinaryCtl,
 * it will be freed when _Delete routine is called.
 */
fatBinaryCtlError_t fatBinaryCtl_Compile(fatBinaryCtl_t handle, void **elf, size_t *esize)
{
    return FBCTL_ERROR_NONE;
}

/*
 * Similar to fatBinaryCtl_Compile with extra support for
 * specifying the directory from where JIT compiler is to be loaded.
 */
fatBinaryCtlError_t fatBinaryCtl_Compile_WithJITDir(fatBinaryCtl_t handle, void **elf,
                                                    size_t *esize, const char *jitDir)
{
    return FBCTL_ERROR_NONE;
}

/* If *_Compile returned an error, get the error log */
fatBinaryCtlError_t fatBinaryCtl_GetCompileLog(fatBinaryCtl_t handle, char **log)
{
    return FBCTL_ERROR_NONE;
}

/* Return the candidate found */
fatBinaryCtlError_t fatBinaryCtl_GetCandidate(fatBinaryCtl_ct handle, void **binary,
                                              fatBinaryCodeKind *kind, size_t *size)
{
    return FBCTL_ERROR_NONE;
}

#ifdef __cplusplus
}
#endif

#endif /* __FATBINARYCTL_H__ */